#include <gtest\gtest.h>
#include <Zaf\Enum.h>



ZafEnum(EnumType, unsigned int) {

	One = 1,
	Two = 2,
	Three = 3,
};



TEST(Enum, Enum) {

	//Constructors
	EnumType e1 = EnumType::One;
	EnumType e2 = e1;
	EnumType e3 = (EnumType)1;

	//Copy constructors
	EnumType e4;
	e4 = EnumType::One;

	EnumType e5;
	e5 = e1;

	EnumType e6;
	e6 = (EnumType)1;

	//Assign operator
	e4 = EnumType::One;
	e5 = e1;
	e6 = (EnumType)1;

	//Assigned to non-enum type
	EnumType::EnumTypeEnum ee = e1;
	int ev = e1;

	e1 = EnumType::One;
	e2 = EnumType::Two;
	e3 = EnumType::Three;

	//operator==
	ASSERT_TRUE(e1 == e1);
	ASSERT_TRUE(e1 == EnumType::One);
	ASSERT_TRUE(EnumType::One == e1);

	//operator!=
	ASSERT_TRUE(e1 != e2);
	ASSERT_TRUE(e1 != EnumType::Two);
	ASSERT_TRUE(EnumType::Two != e1);

	//operator<
	ASSERT_TRUE(e2 < e3);
	ASSERT_TRUE(e2 < EnumType::Three);
	ASSERT_TRUE(EnumType::Two < e3);

	//operator<=
	ASSERT_TRUE(e2 <= e3);
	ASSERT_TRUE(e2 <= e2);
	ASSERT_TRUE(e2 <= EnumType::Three);
	ASSERT_TRUE(e2 <= e2);
	ASSERT_TRUE(EnumType::One <= e2);
	ASSERT_TRUE(EnumType::Two <= e2);

	//operator>
	ASSERT_TRUE(e2 > e1);
	ASSERT_TRUE(e2 > EnumType::One);
	ASSERT_TRUE(EnumType::Three > e2);

	//operator=>
	ASSERT_TRUE(e2 >= e1);
	ASSERT_TRUE(e2 >= e2);
	ASSERT_TRUE(e2 >= EnumType::One);
	ASSERT_TRUE(e2 >= EnumType::Two);
	ASSERT_TRUE(EnumType::Three >= e2);
	ASSERT_TRUE(EnumType::Two >= e2);
}



ZafFlagEnum(Style, unsigned int) {

	Visible = 0x1,
	Border = 0x2,
	Title = 0x4,
};



TEST(Enum, FlagEnum) {

	Style s1 = Style::Visible;
	Style s2 = Style::Border;
	Style s3 = Style::Title;

	// ~
	ASSERT_TRUE(~s1 == 0xfffffffe);
	ASSERT_TRUE(~Style::Visible == 0xfffffffe);

	// |
	ASSERT_TRUE((s1 | s2) == 0x03);
	ASSERT_TRUE((s1 | Style::Border) == 0x03);
	ASSERT_TRUE((Style::Visible | s2) == 0x03);
	ASSERT_TRUE((Style::Visible | Style::Border) == 0x03);

	// &
	Style s4 = Style::Visible | Style::Border;
	ASSERT_TRUE((s4 & s1) == 0x01);
	ASSERT_TRUE((s4 & Style::Border) == 0x02);
	ASSERT_TRUE((Style::Visible & s4) == 0x01);
	ASSERT_TRUE((Style::Visible & Style::Border) == 0x00);

	// ^
	ASSERT_TRUE((s1 ^ s2) == 0x03);
	ASSERT_TRUE((s1 ^ Style::Border) == 0x03);
	ASSERT_TRUE((Style::Border ^ s1) == 0x03);
	ASSERT_TRUE((Style::Border ^ Style::Visible) == 0x03);

	// |=
	s1 = Style::Visible;
	s1 |= s2;
	ASSERT_TRUE(s1 == 0x03);

	s1 = Style::Visible;
	s1 |= Style::Border;
	ASSERT_TRUE(s1 == 0x03);

	Style::StyleEnum se1 = Style::Visible;
	se1 |= s2;
	ASSERT_TRUE(se1 == 0x03);

	se1 = Style::Visible;
	se1 |= Style::Border;
	ASSERT_TRUE(se1 == 0x03);

	// &=
	s1 = Style::Visible | Style::Border;
	s1 &= s2;
	ASSERT_TRUE(s1 == 0x02);

	s1 = Style::Visible | Style::Border;
	s1 &= Style::Border;
	ASSERT_TRUE(s1 == 0x02);

	se1 = Style::Visible | Style::Border;
	se1 &= s2;
	ASSERT_TRUE(se1 == 0x02);

	se1 = Style::Visible | Style::Border;
	se1 &= Style::Border;
	ASSERT_TRUE(se1 == 0x02);

	// ^=
	s1 = Style::Visible;
	s1 ^= s2;
	ASSERT_TRUE(s1 == 0x03);

	s1 = Style::Visible;
	s1 ^= Style::Border;
	ASSERT_TRUE(s1 == 0x03);

	se1 = Style::Visible;
	se1 ^= s2;
	ASSERT_TRUE(se1 == 0x03);

	se1 = Style::Visible;
	se1 ^= Style::Border;
	ASSERT_TRUE(se1 == 0x03);
}